package com.ruoyi.system.service.impl;

import java.math.RoundingMode;
import java.util.List;
import java.util.Date;
import java.math.BigDecimal;
import java.util.concurrent.locks.ReentrantLock;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.SysFee;
import com.ruoyi.system.mapper.SysFeeMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysCheckIn;
import com.ruoyi.system.mapper.SysCheckInMapper;
import com.ruoyi.system.service.ISysCheckInService;
import com.ruoyi.system.service.ISysFeeService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.service.ISysMessageService;

/**
 * 签到管理Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class SysCheckInServiceImpl implements ISysCheckInService
{
    @Autowired
    private SysCheckInMapper sysCheckInMapper;

    @Autowired
    private ISysFeeService sysFeeService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysMessageService messageService;

    private  static ReentrantLock lock = new ReentrantLock();

    private static ReentrantLock lock2 = new ReentrantLock();
    @Autowired
    private SysFeeMapper sysFeeMapper;
    @Autowired
    private SysUserMapper sysUserMapper;


    /**
     * 查询签到管理
     * 
     * @param checkInId 签到管理主键
     * @return 签到管理
     */
    @Override
    public SysCheckIn selectSysCheckInByCheckInId(Long checkInId)
    {
        SysCheckIn sysCheckIn = sysCheckInMapper.selectSysCheckInByCheckInId(checkInId);
        Long elderUserId = sysCheckIn.getElderUserId();
        SysUser sysUser = sysUserMapper.selectUserById(elderUserId);
        sysCheckIn.setBalance(sysUser.getBalance());
        return sysCheckIn;
    }

    /**
     * 查询签到管理列表
     * 
     * @param sysCheckIn 签到管理
     * @return 签到管理
     */
    @Override
    public List<SysCheckIn> selectSysCheckInList(SysCheckIn sysCheckIn)
    {
        return sysCheckInMapper.selectSysCheckInList(sysCheckIn);
    }

    /**
     * 新增签到管理
     * 
     * @param sysCheckIn 签到管理
     * @return 结果
     */
    @Override
    public int insertSysCheckIn(SysCheckIn sysCheckIn)
    {

        lock.lock();

        int i;

        try{

            SysCheckIn checkIn = new SysCheckIn();
            //床位id
            Long bedId = sysCheckIn.getBedId();
            //是否退房 (0代表未退房，1代表已退房)
            String status = "0";
            checkIn.setBedId(bedId);
            checkIn.setStatus(status);
            //默认一个月30天费用
            BigDecimal monthlyFee = sysCheckIn.getMonthlyFee();
            //平均一天费用
            BigDecimal subtract = monthlyFee.divide(new BigDecimal(30),2, RoundingMode.HALF_UP);
            //预计入住时间
            Date checkInTime = sysCheckIn.getCheckInTime();
            //预计退房时间
            Date expectedCheckOutTime = sysCheckIn.getExpectedCheckOutTime();
            int i1 = DateUtils.differentDaysByMillisecond(checkInTime, expectedCheckOutTime);
            //实际费用
            BigDecimal multiply = subtract.multiply(new BigDecimal(i1));

            List<SysCheckIn> sysCheckIns = sysCheckInMapper.selectSysCheckInList(checkIn);
            SysCheckIn checkIn2 = new SysCheckIn();
            checkIn2.setElderUserId(sysCheckIn.getElderUserId());
            checkIn2.setStatus("0");
            List<SysCheckIn> sysCheckIns2 = sysCheckInMapper.selectSysCheckInList(checkIn2);
            if (!sysCheckIns.isEmpty()){
                lock.unlock();
                throw new ServiceException("该床位已有入住记录，请选择其他床位");
            }
            if (!sysCheckIns2.isEmpty()){
                lock.unlock();
                throw new ServiceException("该用户已有入住记录，请选择其他用户");
            }
            sysCheckIn.setMonthlyFee(multiply);
            i = sysCheckInMapper.insertSysCheckIn(sysCheckIn);
        }finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return i;
    }

    /**
     * 修改签到管理
     * 
     * @param sysCheckIn 签到管理
     * @return 结果
     */
    @Override
    public int updateSysCheckIn(SysCheckIn sysCheckIn)
    {
        lock2.lock();
        int i;
        try{
            SysCheckIn checkIn = new SysCheckIn();
            //床位id
            Long bedId = sysCheckIn.getBedId();
            checkIn.setBedId(bedId);

            //默认一个月30天费用
            BigDecimal monthlyFee = sysCheckIn.getMonthlyFee();
            //平均一天费用
            BigDecimal subtract = monthlyFee.divide(new BigDecimal(30),2, RoundingMode.HALF_UP);
            //预计入住时间
            Date checkInTime = sysCheckIn.getCheckInTime();
            //预计退房时间
            Date expectedCheckOutTime = sysCheckIn.getExpectedCheckOutTime();
            int i1 = DateUtils.differentDaysByMillisecond(checkInTime, expectedCheckOutTime);
            //实际费用
            BigDecimal multiply = subtract.multiply(new BigDecimal(i1));
            //是否退房 (0代表未退房，1代表已退房)
            String status = "0";
            checkIn.setStatus(status);
            checkIn.setElderUserId(sysCheckIn.getElderUserId());
            SysCheckIn sysCheckIn1 = sysCheckInMapper.selectSysCheckInByCheckInId(sysCheckIn.getId());
            if (!sysCheckIn1.getBedId().equals(bedId)) {
                List<SysCheckIn> sysCheckIns = sysCheckInMapper.selectSysCheckInList(checkIn);
                if (!sysCheckIns.isEmpty()) {
                    throw new ServiceException("该床位已有入住记录，请选择其他床位");
                }
            }
            sysCheckIn.setMonthlyFee(multiply);
           i = sysCheckInMapper.updateSysCheckIn(sysCheckIn);
        }finally {
            if (lock2.isHeldByCurrentThread()) {
                lock2.unlock();
            }
        }
        return i;
    }

    /**
     * 批量删除签到管理
     * 
     * @param checkInIds 需要删除的签到管理主键
     * @return 结果
     */
    @Override
    public int deleteSysCheckInByCheckInIds(Long[] checkInIds)
    {
        return sysCheckInMapper.deleteSysCheckInByCheckInIds(checkInIds);
    }

    /**
     * 删除签到管理信息
     * 
     * @param checkInId 签到管理主键
     * @return 结果
     */
    @Override
    public int deleteSysCheckInByCheckInId(Long checkInId)
    {
        return sysCheckInMapper.deleteSysCheckInByCheckInId(checkInId);
    }

    /**
     * 查询待处理的签到记录
     * 
     * @return 签到记录列表
     */
    @Override
    public List<SysCheckIn> selectPendingCheckIns()
    {
        SysCheckIn checkIn = new SysCheckIn();
        checkIn.setStatus("0"); // 设置状态为待处理
        return sysCheckInMapper.selectSysCheckInList(checkIn);
    }

    /**
     * 根据老人用户ID查询入住记录
     * 
     * @param elderUserId 老人用户ID
     * @return 入住管理集合
     */
    @Override
    public List<SysCheckIn> selectSysCheckInByElderUserId(Long elderUserId)
    {
        return sysCheckInMapper.selectSysCheckInByElderUserId(elderUserId);
    }

    /**
     * 审核入住申请
     * 
     * @param checkInId 入住记录ID
     * @param auditStatus 审核状态
     * @param auditRemark 审核备注
     * @param monthlyFee 每月费用
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, DuplicateKeyException.class})
    public int auditSysCheckIn(Long checkInId, String auditStatus, String auditRemark, BigDecimal monthlyFee)
    {
        SysCheckIn checkIn = new SysCheckIn();
        checkIn.setId(checkInId);
        checkIn.setAuditStatus(auditStatus);
        checkIn.setAuditRemark(auditRemark);
        checkIn.setAuditBy(SecurityUtils.getUsername());
        checkIn.setAuditTime(new Date());

        // 如果审核通过，处理入住费用
        if ("1".equals(auditStatus)) {
            // 获取完整的入住信息
            SysCheckIn fullCheckIn = sysCheckInMapper.selectSysCheckInByCheckInId(checkInId);
            if (fullCheckIn == null) {
                throw new ServiceException("入住记录不存在");
            }

            // 获取老人信息和余额
            SysUser elder = userService.selectUserById(fullCheckIn.getElderUserId());
            if (elder == null) {
                throw new ServiceException("老人信息不存在");
            }

            BigDecimal balance = elder.getBalance();
            if (balance == null) {
                balance = BigDecimal.ZERO;
            }

            // 检查余额是否足够
            if (balance.compareTo(monthlyFee) < 0) {
                // 发送余额不足提醒
                messageService.sendBalanceReminder(elder, balance.doubleValue());
                System.out.println("==== 已成功发送余额不足提醒，老人ID：" + elder.getUserId() + "，余额：" + balance + " ====");
                return -2;
            }
            //2代表入住费用
            // 处理入住费用
            sysFeeService.handleCheckInFee(fullCheckIn.getElderUserId(), monthlyFee,"2");
            
            // 检查余额是否低于阈值（例如500元），发送提醒
            if (balance.subtract(monthlyFee).compareTo(new BigDecimal(500)) < 0) {
                messageService.sendBalanceReminder(elder, balance.subtract(monthlyFee).doubleValue());
            }
        }

        return sysCheckInMapper.updateSysCheckIn(checkIn);
    }

    /**
     * 办理退住
     * 
     * @param checkInId 入住记录ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, DuplicateKeyException.class})
    public int checkOut(Long checkInId)
    {
        // 1. 获取入住记录
        SysCheckIn checkIn = sysCheckInMapper.selectSysCheckInByCheckInId(checkInId);

        if (checkIn == null)
        {
            throw new ServiceException("入住记录不存在");
        }

        // 2. 更新入住记录状态
        // 设置为已退住
        checkIn.setStatus("1");
        // 设置实际退住时间
        checkIn.setActualCheckOutTime(new Date());
        SysUser sysUser = userService.selectUserById(checkIn.getElderUserId());

        //老人余额
        BigDecimal balance = sysUser.getBalance();
        // 3. 更新老人状态和余额
        SysUser elder = new SysUser();
        elder.setUserId(checkIn.getElderUserId());
        // 设置为已退住
        elder.setInHospitalStatus("3");
        // 清空余额
        elder.setBalance(BigDecimal.ZERO);

        userService.updateUser(elder);
        // 4 处理退费
        SysFee sysFee = new SysFee();
        setSysFee(sysFee, sysUser, balance);
        sysFeeMapper.insertSysFee(sysFee);
        
        // 5. 发送退住通知
        messageService.sendCheckOutNotification(sysUser, checkIn.getBedName());
        
        return sysCheckInMapper.updateSysCheckIn(checkIn);
    }

    private  void setSysFee(SysFee sysFee, SysUser sysUser, BigDecimal balance) {
        sysFee.setElderUserId(sysUser.getUserId());
        sysFee.setElderUserName(sysUser.getNickName());
        //退费类型 -- 4
        sysFee.setFeeType("4");
        //还用取相反数
        sysFee.setAmount(balance.negate());
        //已退款
        sysFee.setPaymentStatus("2");
        sysFee.setPaymentMethod("0");
        sysFee.setPaymentTime(DateUtils.getNowDate());
        sysFee.setMonth(DateUtils.parseDateToStr("yyyy-MM", DateUtils.getNowDate()));
        sysFee.setBillNo(DateUtils.dateTimeNow() + RandomStringUtils.randomNumeric(6));
    }
} 